//===========================================================================================
#include <dylab/utils/geometry/TetrahedronGeometry.h>
#include <dylab/utils/exceptions/EVerificationFailed.h>
#include "TriangleGeometry3_Tests.h"
#include "EdgeGeometry3_Tests.h"
//-----------------------------------------------------------------------------
void runPointInTetrahedronTest(const TetrahedronGeometry & _tetraGeom, const Vector3 & _p, const TetrahedronGeometry::pointcls_t & _correctCls)
{
    TetrahedronGeometry::pointcls_t pointCls = _tetraGeom.classifyPoint(_p);

    // test, if cetner is inside based on barycentric coords    
    DYLAB_LOGF3("\t\t classifyPoint(%1%) = %2% (correctCls = %3%)", _p, pointCls, _correctCls);

    // verify point classification
    DYLAB_VERIFY(pointCls.first == _correctCls.first);
    switch (pointCls.first)
    {
    case Math::POINTCLS_VERTEX:
        DYLAB_VERIFY(pointCls.second.vertexIdx == _correctCls.second.vertexIdx);
        break;
    case Math::POINTCLS_EDGE:
        DYLAB_VERIFY(pointCls.second.edgeIdx == _correctCls.second.edgeIdx);
        break;
    case Math::POINTCLS_FACE:
        DYLAB_VERIFY(pointCls.second.faceIdx == _correctCls.second.faceIdx);
        break;
    }    
}
//-----------------------------------------------------------------------------
void runTetrahedronTests(const TetrahedronGeometry & _tetraGeom)
{ DYLAB_TRACE_CALLS

    // log tested tetrahedron info
    DYLAB_LOGF("Testing _tetraGeom: %1% ... ", _tetraGeom);

    // compute value & volume of the tetrahedron
    DYLAB_LOGF2("\tcomputeValue() = %1%, computeVolume() = %2%", _tetraGeom.computeValue(), _tetraGeom.computeVolume());

    // degeneration test
    DYLAB_LOGF("\tisDegenerated() = %1%", _tetraGeom.isDegenerated());
    DYLAB_VERIFY(!_tetraGeom.isDegenerated());

    // compute tetrahedron center
    DYLAB_LOGF("\tcomputeCenter() = %1%", _tetraGeom.computeCenter());

    // compute barycetric coords of the its cetner
    DYLAB_LOGF("\tcomputeBarycetricCoords(computeCenter()) = %1%", _tetraGeom.computeBarycentricCoords(_tetraGeom.computeCenter()));
    DYLAB_VERIFY(_tetraGeom.computeBarycentricCoords(_tetraGeom.computeCenter()).almostEqual(Vector4::ONE / DYLAB_R(4)));

    // check, if the center is inside its tetrahedron
    runPointInTetrahedronTest(_tetraGeom, _tetraGeom.computeCenter(), TetrahedronGeometry::pointcls_t(Math::POINTCLS_INNER, TetrahedronGeometry::FeatureIdx()));

    DYLAB_LOG("");

    // print its vertices
    for (TetrahedronGeometry::VertexIdxIterator vertexIdx; vertexIdx.isValid(); vertexIdx++)
    {
        DYLAB_LOGF("\tcontains vertex: %1%", _tetraGeom[vertexIdx]);

        // and check, if they are inside
        runPointInTetrahedronTest(_tetraGeom, _tetraGeom[vertexIdx], TetrahedronGeometry::pointcls_t(Math::POINTCLS_VERTEX, *vertexIdx));
    }

    DYLAB_LOG("\n");

    // now print its edges ...
    for (TetrahedronGeometry::EdgeIdxIterator edgeIdx; edgeIdx.isValid(); edgeIdx++)
    {
        DYLAB_LOGF("\tcontains edge: %1%", _tetraGeom.getEdgeGeometry(edgeIdx));

        // and check, if their mid-points are inside
        runPointInTetrahedronTest(_tetraGeom, _tetraGeom.getEdgeGeometry(edgeIdx).computeCenter(), TetrahedronGeometry::pointcls_t(Math::POINTCLS_EDGE, *edgeIdx));

        // run the edge tests
        DYLAB_LOG("");
        DYLAB_LOG("//-----------------------------------------------------------------------------");
        DYLAB_LOG("");
        runEdgeTests(_tetraGeom.getEdgeGeometry(edgeIdx));
        DYLAB_LOG("");
        DYLAB_LOG("//-----------------------------------------------------------------------------");
        DYLAB_LOG("");
    }

    DYLAB_LOG("\n");

    // .. and faces
    for (TetrahedronGeometry::FaceIdxIterator faceIdx; faceIdx.isValid(); faceIdx++)
    {
        DYLAB_LOGF("\tcontains face: %1%", _tetraGeom.getFaceGeometry(faceIdx));

        // and check, if their center-points are inside
        runPointInTetrahedronTest(_tetraGeom, _tetraGeom.getFaceGeometry(faceIdx).computeCenter(), TetrahedronGeometry::pointcls_t(Math::POINTCLS_FACE, *faceIdx));

        // run the triangle tests
        DYLAB_LOG("");
        DYLAB_LOG("//-----------------------------------------------------------------------------");
        DYLAB_LOG("");
        runTriangleTests(_tetraGeom.getFaceGeometry(faceIdx));
        DYLAB_LOG("");
        DYLAB_LOG("//-----------------------------------------------------------------------------");
        DYLAB_LOG("");
    }
     }
//===========================================================================================